package com.zt.questionnaire.common;


import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.nimbusds.jose.JOSEException;
import com.zt.questionnaire.common.config.redis.CacheOperator;
import com.zt.questionnaire.db.MyMapper;
import com.zt.questionnaire.common.utils.JsonUtils;
import com.zt.questionnaire.common.utils.RandomUtil;
import com.zt.questionnaire.common.utils.ServletUtils;
import com.zt.questionnaire.common.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.HttpServletRequest;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.List;

@Slf4j
@Component
public class HService extends HConstant {

    /**
     * 支付的时候默认的公众号tag
     **/
    public static final String wx_pub_tag_def = "yueyoujiankang";

    //以下是账号登录的时候存储的一些信息====================================
    /**
     * 登录时存储的信息：账号的一级分类，0表示是用户（普通用户[患者]、养生馆技师[员工]），1表示管理员登录，2表示大屏机登录
     **/
    public static final String attr_login_type_first = "type_frist";
    /**
     * 账号id，只有用户才有，管理员没有
     **/
    public static final String attr_login_id = "id";
    /**
     * 账号：用户、管理员的手机号码，大屏机的udid
     **/
    public static final String attr_login_phone = "phone";
    public static final String attr_login_name = "name";
    public static final String attr_login_icon = "picture";
    public static final String attr_login_im = "im";
    public static final String attr_login_type = "type";
    /**
     * 除平台管理员外的其他管理员权限列表
     ***/
    public static final String attr_login_admin_permission = "permission";
    /**
     * 关系，如果是管理员，表示管理员归属的机构单位id，如果是普通用户，当是技师表示技师归属的养生馆（单位），当是普通用户1=推荐人，2=老板空（1/2会并存，空表示普通用户）
     **/
    public static final String attr_login_relation = "relation";
    /**
     * 第三方登录时的openId，目前主要用于公众号用户还没有创建账号的时候通过openId绑定的一些关系（例如：和技师绑定关系后期会话、通过客服消息对技师的服务进行评价）
     **/
    public static final String attr_login_channel_open_id = "open_id";
    /**
     * 第三方登录时的session_key，用来校验是否过期，
     **/
    public static final String attr_login_channel_session_key = "session_key";
    /**
     * 第三方登录时的union_id
     **/
    public static final String attr_login_channel_unionid = "union_id";
    /**
     * 扩展参数：目前手提箱设备登录绑定的医生账号token，手提箱登录的时候把在这台设备登录的医生token保存下面
     **/
    public static final String attr_login_extend = "extend";


    //以下是客户端在消息头里带给服务器的参数====================================
    public static final String attr_req_token = "token";
    /**
     * 登录来源，常量在 AccountService 类里面
     **/
    public static final String attr_req_source = "source";
    /**
     * 版本平台
     **/
    public static final String attr_req_platform = "platform";
    /**
     * 版本号
     **/
    public static final String attr_req_ver = "ver";
    /**
     * 公众号、小程序关联的tag（单位唯一标识）、大屏机绑定的公众号tag，登录的时候，当时这三种类型，必须要有tag
     **/
    public static final String attr_req_tag = "tag";
    /**
     * 除平台管理员外的其他管理员权限,后台管理工具页面带入的，当前操作归属的最小权限（针对权限表里的最小权限，如果表里没有配置二级菜单项，就是一级菜单项）
     ***/
    public static final String attr_req_admin_permission = "req_permission";

    /**
     * ios内购的商品id前缀，所有的商品都用这个前缀
     **/
    public static final String ios_product = "product_";


//	/**统计类型：用户注册次数（同一个用户每天对同一个类型的统计只统计一次）*/
//	public static int type_register = 0;
//	/**统计类型：用户登录次数（同一个用户每天对同一个类型的统计只统计一次）*/
//	public static int type_login = 1;
//	/**统计类型：打开疾病库（同一个用户每天对同一个类型的统计只统计一次）*/
//	public static int type_illness_open = 2;
//	/**统计类型：打开穴位库（同一个用户每天对同一个类型的统计只统计一次）*/
//	public static int type_points_open = 3;
//	/**统计类型：查看健康推送消息（同一个用户每天对同一个类型的统计只统计一次）*/
//	public static int type_push_list = 4;
//	/**统计类型：查看测试报告详情（同一个用户每天对同一个类型的统计只统计一次）*/
//	public static int type_report_list = 5;
//	/**统计类型：点我提问（触发测试）（同一个用户每天对同一个类型的统计只统计一次）*/
//	public static int type_ask = 6;
//	/**统计类型：打开小儿推拿模块（同一个用户每天对同一个类型的统计只统计一次）*/
//	public static int type_child_massage_open = 7;
//	/**统计类型：小儿推拿模块付费（同一个用户每天对同一个类型的统计只统计一次）*/
//	public static int type_child_massage_pay = 8;

//	/** 统计类型：打开疾病库（同一个用户每天对同一个类型的统计只统计一次） */
//	public static String type_illness_open = "2";
//	/** 统计类型：打开穴位库（同一个用户每天对同一个类型的统计只统计一次） */
//	public static String type_points_open = "3";


    /**
     * tb_img_manager表中的type类型，问诊结果推送需要的图片
     */
    public static String img_type_result = "result";
    /**
     * tb_img_manager表中的type类型，通过app客户触发的公众号支付消息的图片
     */
    public static String img_type_pay = "pay";
    /**
     * tb_img_manager表中的type类型，获取完整版的问诊问题列表的图片
     */
    public static String img_type_inquiry = "inquiry";
    /**
     * tb_img_manager表中的type类型，脑卒中报告图标
     */
    public static String img_type_stroke_report = "stroke_report";
    /**
     * tb_img_manager表中的type类型，推荐体质测试入口的图标
     */
    public static String img_type_habitus_report = "habitus_report";


    /**
     * 账号的一级分类：用户（普通用户[患者]、养生馆技师[员工]、医生）
     **/
    public static final int type_first_account = 0;

    /**
     * 账号的一级分类：管理员登录
     **/
    public static final int type_first_admin = 1;

    /**
     * 账号的一级分类：大屏机登录
     **/
    public static final int type_first_unit_device = 2;


    /**
     * 管理员类型：平台管理员
     **/
    public static final int admin_type_platform = 1;

    /**
     * 管理员类型：医院超级管理员
     **/
    public static final int admin_type_hospital = 2;

    /**
     * 管理员类型：有大屏机的养生馆
     **/
    public static final int admin_type_health_pad = 3;

    /**
     * 管理员类型：没有大屏机的养生馆
     **/
    public static final int admin_type_health = 4;

    /**
     * 管理员类型：养生馆的员工账号（目前只有查看用户数据，有大屏机的养生馆，患者在大屏机测试后，如果技师是通过电脑查看报告，需要此类型的账号）
     **/
    public static final int admin_type_health_employee = 5;

    /**
     * 管理员类型：其他有大屏机的单位机构（例如卖养生酒的、公司的、开会的等）
     **/
    public static final int admin_type_other = 6;

    /**
     * 管理员类型：公众号相关的机构
     **/
    public static final int admin_type_wx_public = 7;

    /**
     * 管理员类型：查看小儿体测数据的医生账号
     **/
    public static final int admin_type_child = 10;
    /**
     * 管理员类型：药房
     **/
    public static final int admin_type_pharmacy = 11;

    /**
     * 管理员类型：工厂
     **/
    public static final int admin_type_factory = 12;

    /**
     * 管理员类型：学校管理员，管理学生穴位学习
     **/
    public static final int admin_type_school = 20;

    /**
     * 账号类型：普通用户
     */
    public static final int type_user = 0;
//    /**
//     * 账号类型：技师
//     */
//    public static final int type_health_employee = 1;
    /**
     * 账号类型：老板（例如：养生馆老板，由经销商添加）
     */
    public static final int type_boss = 2;
    /**
     * 账号类型：经销商（城市代理人，由后台工具添加）)
     */
    public static final int type_city = 3;
    /**
     * 账号类型：医生，目前只有苏小莹，回复用户咨询信息
     */
    public static final int type_doctor = 4;
    /**
     * 账号类型：药师
     */
    public static final int type_pharmacy = 5;


    /**
     * 账号类型：小程序普通用户
     */
    public static final int type_user_wx_mini_app = 7;


    /**
     * 报告类型：单病种风险筛查=11，痛症=12
     */
    public static final int report_type_risk = 11;
    /**
     * 报告类型：单病种风险筛查=11，痛症=12
     */
    public static final int report_type_pain = 12;


    @Autowired
    private CacheOperator redis;

    public static String getIosOrAndroid(HttpServletRequest request) {
        //platform表示各个平台的关键字，这里处理如果不是苹果(I)，就默认为安装(A)
        String platform = request.getHeader(HService.attr_req_platform);
        log.info("消息头参数platform={}", platform);
        if (!platform_ios.equals(platform)) {
            platform = platform_android;
        }
        return platform;
    }

    public static String getIp(HttpServletRequest request) {
        return ServletUtils.realIp(request);
    }

    public static void setSourceLogin(HttpServletRequest req, String source) {
        req.setAttribute(attr_req_source, source);
//		System.out.println(getSource(req));
    }

    public static String getSourceLogin(HttpServletRequest req) {
        Object attribute = req.getAttribute(attr_req_source);
        if (attribute == null) {
            return null;
        }
        return (String) attribute;
    }

    /**
     * 获取除平台管理员外的其他管理员权限列表
     *
     * @param req
     * @return
     */
    public static List<Integer> getAdminPermission(HttpServletRequest req) {
        Object attribute = req.getAttribute(attr_login_admin_permission);
        if (attribute == null) {
            return null;
        }
        return JsonUtils.toList(attribute.toString(), Integer.class);
    }

    public static void setOpenId(HttpServletRequest req, String openId) {
        req.setAttribute(attr_login_channel_open_id, openId);
    }

    public static String getOpenId(HttpServletRequest req) {
        return (String) req.getAttribute(attr_login_channel_open_id);
    }

    public static String setUnionid(HttpServletRequest req) {
        return (String) req.getAttribute(attr_login_channel_unionid);
    }

    public static String getUnionid(HttpServletRequest req) {
        return (String) req.getAttribute(attr_login_channel_unionid);
    }

    public static String setSessionKey(HttpServletRequest req) {
        return (String) req.getAttribute(attr_login_channel_session_key);
    }

    public static String getSessionKey(HttpServletRequest req) {
        return (String) req.getAttribute(attr_login_channel_session_key);
    }

    public static void setTag(HttpServletRequest req, String tag) {
        req.setAttribute(attr_req_tag, tag);
    }

//    public String getDoctorName(HttpServletRequest req) throws ParseException, JOSEException {
//        Map<String, Object> map = getDoctorParam(req);
//        if (map == null) {
//            return null;
//        }
//        return (String) map.get(attr_login_name);
//    }
//
//    public String getDoctorPhone(HttpServletRequest req) throws ParseException, JOSEException {
//        Map<String, Object> map = getDoctorParam(req);
//        if (map == null) {
//            return null;
//        }
//        return (String) map.get(attr_login_phone);
//    }

    public static String getTag(HttpServletRequest req) {
        return (String) req.getAttribute(attr_req_tag);
    }

    public static Long getTypeFirst(HttpServletRequest request) {
        Long admin = (Long) request.getAttribute(attr_login_type_first);
        if (admin == null) {
            //表示错误
            return -1L;
        }
        return admin;
    }

    /**
     * 是否是用户
     *
     * @param request
     * @return
     */
    public static boolean isAccount(HttpServletRequest request) {
        Long type = getTypeFirst(request);
        if (type == null) {
            return false;
        }
        if (type != type_first_account) {
            return true;
        }
        Integer accountType = getType(request);
        if (accountType == null || accountType != type_user) {
            return false;
        }
        return true;
    }

    /**
     * 是否是管理员，包括所有管理员类型（平台管理员、单位管理员、员工管理员）
     *
     * @param request
     * @return
     */
    public static boolean isAdmin(HttpServletRequest request) {
        Long type = getTypeFirst(request);
        if (type == null) {
            return false;
        }
        if (type == type_first_admin) {
            return true;
        }
        return false;
    }

    /**
     * 是否是单位设备登录（大屏机登录）
     *
     * @param request
     * @return
     */
    public static boolean isUnitDevice(HttpServletRequest request) {
        Long type = getTypeFirst(request);
        if (type == null) {
            return false;
        }
        if (type == type_first_unit_device) {
            return true;
        }
        return false;
    }

    /**
     * 获取账号id，只有用户才有，管理员没有
     *
     * @param request
     * @return
     */
    public static Long getAccountId(HttpServletRequest request) {
        return (Long) request.getAttribute(attr_login_id);
    }


    /**
     * 获取账号类型，常量在accountService里面
     **/
    public static Integer getType(HttpServletRequest request) {
        Object type = request.getAttribute(attr_login_type);
        if (type == null) {
            return null;
        }
        return Integer.parseInt(type.toString());
    }

    public static String getPhone(HttpServletRequest request) {
        return (String) request.getAttribute(attr_login_phone);
    }


    public static String getName(HttpServletRequest request) {
        return (String) request.getAttribute(attr_login_name);
    }

    public static String getPicture(HttpServletRequest request) {
        return (String) request.getAttribute(attr_login_icon);
    }

    public static String getImName(HttpServletRequest request) {
        return (String) request.getAttribute(attr_login_im);
    }

    /**
     * 关系id。
     * 如果是管理员，表示管理员归属的单位id，
     * 如果是账号，当是技师表示技师归属的养生馆（单位）
     * 如果是大屏机，表示大屏机归属的单位id
     *
     * @param request
     * @return
     */
    public static Long getRelation(HttpServletRequest request) {
        Object obj = request.getAttribute(attr_login_relation);
        if (obj == null) {
            return null;
        }
        return Long.parseLong(obj.toString());
    }

    /**
     * 管理员归属的单位id
     *
     * @param request
     * @return
     */
    public static Long getAdminUnitId(HttpServletRequest request) {
        return getRelation(request);
    }

    /**
     * 员工（养生馆技师）的单位id
     *
     * @param request
     * @return
     */
    public static Long getEmployeeUnitId(HttpServletRequest request) {
        return getAdminUnitId(request);
    }

    /**
     * 当时大屏机登录的时候，大屏机设备的唯一编码
     *
     * @param request
     * @return
     */
    public static String getDeviceUdid(HttpServletRequest request) {
        return getPhone(request);
    }

    /**
     * 当时大屏机登录的时候，大屏机的设备id
     *
     * @param request
     * @return
     */
    public static Long getDeviceId(HttpServletRequest request) {
        return getAccountId(request);
    }

    /**
     * 当时大屏机登录的时候，大屏机归属的单位id
     *
     * @param request
     * @return
     */
    public static Long getDeviceUnitId(HttpServletRequest request) {
        return getRelation(request);
    }

    /**
     * 验证管理员是否有操作指定单位机构的权限，调用的前提是保证是平台管理员或单位管理员，平台管理员直接通过
     *
     * @param request
     * @param unitId  单位第
     * @return
     */
    public static boolean isAdminRelation(HttpServletRequest request, long unitId) {
        Long relation = getRelation(request);
        if (relation == null) {
            //平台管理员
            return true;
        }
        if (unitId != relation) {
            return false;
        }
        return true;
    }

    /**
     * 验证员工（技师）是否是操作自己归属的单位相关信息，调用的前提是保证是技师
     *
     * @param request
     * @param unitId
     * @return
     */
    public static boolean isEmployeeRelation(HttpServletRequest request, long unitId) {
        Long relation = getRelation(request);
        if (relation == null || unitId != relation) {
            return false;
        }
        return true;
    }


    /**
     * 是否是平台管理员
     *
     * @param request
     * @return
     */
    public static boolean isAdminPlatform(HttpServletRequest request) {
        boolean admin = isAdmin(request);
        if (!admin) {
            return false;
        }
        Integer type = getType(request);
        if (type == null) {
            return false;
        }
        if (type == admin_type_platform) {
            return true;
        }
        return false;
    }

    /**
     * 是否是单位管理员
     *
     * @param request
     * @return
     */
    public static boolean isAdminUnit(HttpServletRequest request) {
        boolean admin = isAdmin(request);
        if (!admin) {
            return false;
        }
        Integer type = getType(request);
        return isAdminUnit(type);
    }


    /**
     * 是否是单位管理员
     *
     * @param request
     * @return
     */
    public static boolean isAdminUnit(Integer type) {
        if (type == null) {
            return false;
        }
        if (type == admin_type_hospital || type == admin_type_health_pad || type == admin_type_health || type == admin_type_other || type == admin_type_wx_public) {
            return true;
        }
        return false;
    }

    /**
     * 是否是公众号相关单位
     *
     * @param request
     * @return
     */
    public static boolean isAdminUnitWx(Integer type) {
        if (type == null) {
            return false;
        }
        if (type == admin_type_wx_public) {
            return true;
        }
        return false;
    }

//    /**
//     * 是否是养生馆员工
//     *
//     * @param type
//     * @return
//     */
//    public static boolean isAccountHealthEmploy(Integer type) {
//        if (type != null && type == type_health_employee) {
//            return true;
//        }
//        return false;
//    }

    /**
     * 是否是城市代理人（推荐人）
     *
     * @param type
     * @return
     */
    public static boolean isAccountCity(Integer type) {
        if (type != null && type == type_city) {
            return true;
        }
        return false;
    }

//    public static boolean isAccountHealthEmployee(HttpServletRequest request) {
//        boolean is = isAccount(request);
//        if (!is) {
//            return false;
//        }
//        Integer type = getType(request);
//        return isAccountHealthEmploy(type);
//    }

    public static boolean isAccountCity(HttpServletRequest request) {
        boolean is = isAccount(request);
        if (!is) {
            return false;
        }
        Integer type = getType(request);
        return isAccountCity(type);
    }


    public boolean isDoctor(HttpServletRequest request) throws ParseException, JOSEException {
        Long type = getTypeFirst(request);
        if (type == null) {
            return false;
        }
        if (type != type_first_account) {
            return true;
        }
        Integer accountType = getType(request);
        if (accountType == null || accountType != type_doctor) {
            return false;
        }
        return true;
    }


//    public Long getDoctorId(HttpServletRequest request) throws ParseException, JOSEException {
//        Map<String, Object> map = getDoctorParam(request);
//        if (map == null) {
//            return null;
//        }
//        return (Long) map.get(attr_login_id);
//    }

//    private Map<String, Object> getDoctorParam(HttpServletRequest request) throws ParseException, JOSEException {
//        boolean is = isUnitDevice(request);
//        if (!is) {
//            return null;
//        }
//        Object extend = request.getAttribute(attr_login_extend);
//        if (extend == null) {
//            return null;
//        }
//        String token = extend.toString();
//        Map<String, Object> map = TokenUtils.validHS256(token, redis);
//        if (map == null) {
//            return null;
//        }
//        Long type_first = (Long) map.get(attr_login_type_first);
//        if (type_first == null || type_first != type_first_account) {
//            return null;
//        }
//        Long accountType = (Long) map.get(attr_login_type);
//        if (accountType == null || accountType != type_doctor) {
//            return null;
//        }
//        return map;
//    }

//	public static void setDoctorToken(HttpServletRequest req, String token) {
//		req.setAttribute(attr_login_extend, token);
//	}

    /**
     * 获取列表
     *
     * @param mapper
     * @param ex
     * @param page
     * @param num
     * @return
     */
    public static <T> List<T> getList(MyMapper<T> mapper, Example ex, Integer page) {
        return getList(mapper, ex, page, null);
    }

    public static <T> List<T> getList(MyMapper<T> mapper, Example ex, Integer page, Integer num) {
        if (page == null || page <= 0) {
            page = 1;
        }
        if (num == null || num <= 0) {
            num = 10;
        }
        Page<Object> startPage = PageHelper.startPage(page, num);
        List<T> list = mapper.selectByExample(ex);
        int pageCount = startPage.getPages();
        if (pageCount < page) {
            list.clear();
        }
        return list;
    }

    public static <T> PageResult<T> getListAndNum(MyMapper<T> mapper, Example example, Integer page) {
        return getListAndNum(mapper, example, page, null);
    }

    /**
     * 获取列表和总条数
     *
     * @param mapper
     * @param ex
     * @param page
     * @param num
     * @return
     */
    public static <T> PageResult<T> getListAndNum(MyMapper<T> mapper, Example example,
                                                  Integer page, Integer num) {
        if (page == null || page <= 0) {
            page = 1;
        }
        if (num == null || num <= 0) {
            num = 10;
        }
        Page<Object> startPage = PageHelper.startPage(page, num);
        List<T> list = mapper.selectByExample(example);
        int pageCount = startPage.getPages();
        if (pageCount < page) {
            list.clear();
        }
        //即使没有值，也返回对象，避免使用的地方在获取集合的时候抛出空指针异常
        return new PageResult<>(startPage.getTotal(), list);
    }

    /**
     * 将整数转换为double
     *
     * @param num   所需要转换的数字,保留两位小数
     * @param total 基数
     * @return
     */
    public static Double intToDouble(Integer num, Integer total) {
        if (num == null || total == null || num == 0 || total == 0) {
            return 0d;
        }
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(2);
        double n = (double) num / total;
        String result = numberFormat.format(n);
        result = result.replaceAll(",", "");
        return Double.valueOf(result);
    }

    public static Double longToDouble(Long num, Integer total) {
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(2);
        double n = (double) num / total;
        String result = numberFormat.format(n);
        result = result.replaceAll(",", "");
        return Double.valueOf(result);
    }

    public static Long[] getStartAndEnd(Integer page, Integer num) {
        if (page == null || page <= 0) {
            page = 1;
        }
        if (num == null || num <= 0) {
            num = 10;
        }
        long start = (page - 1) * num;
        long end = start + num - 1;

        return new Long[]{start, end};
    }

    /**
     * 生成订单号，后缀是账号id以及随机字符串
     *
     * @param accountId
     * @return
     * @throws Exception
     */
    public static String getOrderIdByAccountId(Long accountId) throws Exception {
        long currTime = TimeUtils.getCurrTime();
        // 微信公众号要求out_trade_no最大长度为32、支付64位
        String orderId = TimeUtils.longToYearMonthDayHourMinSecon(currTime);
        if (accountId != null) {
            orderId += "_" + accountId;
        } else {
            orderId += "_" + RandomUtil.getRandomCode(4);
        }
        orderId += "_" + RandomUtil.getRandomCode(4);
        return orderId;
    }

    public static void main(String[] args) {
//		Integer num = 1027500770;
//		Integer total = 100;
//		Double d = intToDouble(num, total);
        String st = "1,033.47";
        st = st.replaceAll(",", "");
        System.out.println(Double.valueOf(st));
        Integer type = null;
        System.out.println(type == 1);
    }


}
